home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
tool
/
mcfilter
/
mcfilter.c
next >
Wrap
Text File
|
1995-02-15
|
8KB
|
340 lines
/*
MercuryFilter Version 1.00a for All MS-DOS Machines
Copyright (c) 1995 Delmonta all rights reserved.
コンパイルについて:
浮動小数点演算は使用していませんので、printf関数は
doubleに対応していないサブセット版を使用してもかまいません。
*/
#include<ctype.h>
#include<jstring.h>
#include<stdarg.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*****************************************************************************/
/* 下請けルーチン */
/*****************************************************************************/
#define MEMBERSOF(array) (sizeof(array)/sizeof((array)[0]))
static char Separators[] = " \t\n\v";
static int Linepos = 0;
/*--------------------------------エラー終了---------------------------------*/
static void die(char *s,...)
{
va_list ap;
fprintf(stderr,"%d:",Linepos);
va_start(ap,s);
vfprintf(stderr,s,ap);
va_end(ap);
exit(1);
}
/*--------------------文字列の両端の空白類をカットする-----------------------*/
static char *chop(char *s)
{
while (isspace(*s))
s++;
if (*s!='\0')
{
char *p = strchr(s,'\0');
while (isspace(*--p))
;
*(p+1) = '\0';
}
return s;
}
/*-------------------エラー処理を含む文字列の二重化--------------------------*/
static char *xstrdup(char *s)
{
s = strdup(s);
if (s!=NULL)
return s;
die("メモリ不足です\n");
exit(1);
}
/*****************************************************************************/
/* 各キーワードの処理 */
/*---------------------------------------------------------------------------*/
/* 各キーワードを処理する関数が0を返した場合、その行は出力されない */
/*****************************************************************************/
static int Keywordnum = 0;
static int Groupkey_num = 0;
static char *Keyword[32];
static struct
{
char *name;
int keywordid;
} Groupkey[256];
/*------------キーワードテーブルから指定されたキーワードを探す---------------*/
/* 見つからなければエラー終了する。 */
/*---------------------------------------------------------------------------*/
static int find_keyword(char *p)
{
int i;
for (i=0 ; i<Keywordnum ; i++)
{
if (stricmp(p,Keyword[i])==0)
return i;
}
die("キーワード %s は定義されていません\n",p);
exit(1);
}
/*----------------グループキーテーブルからグループキーを探す-----------------*/
/* 見つからなければ黙って-1を返す。 */
/* 返すのは、配列Groupkeyの添え字ではなく、対応するKEYWORDの番号。 */
/*---------------------------------------------------------------------------*/
static int find_groupkey(char *p)
{
int i;
for (i=0 ; i<Groupkey_num ; i++)
{
if (stricmp(p,Groupkey[i].name)==0)
return Groupkey[i].keywordid;
}
return -1;
}
/*--------------------------KEYWORD(1);PROGRAM以前---------------------------*/
static int cmd_keyword_def(char *dst,char *src)
{
char *p;
*dst = '\0';
for (p=jstrtok(src,Separators);p!=NULL;p=jstrtok(NULL,Separators))
{
Keyword[Keywordnum++] = xstrdup(p);
strcat(dst,p);
strcat(dst," ");
}
return 1;
}
/*-------------------------KEYWORD(2);PROGRAM以後----------------------------*/
static int cmd_keyword_ref(char *dst,char *src)
{
char *p;
*dst = '\0';
for (p=jstrtok(src,Separators);p!=NULL;p=jstrtok(NULL,Separators))
{
int n;
n = find_groupkey(p);
if (n>=0)
p = Keyword[n];
else
find_keyword(p);
strcat(dst,p);
strcat(dst," ");
}
return 1;
}
/*---------------------------------GROUP-------------------------------------*/
static int cmd_group(char *dst,char *src)
{
char *p;
int id;
p = jstrtok(src,Separators);
if (p==NULL)
return 0;
id = find_keyword(p);
while ((p=jstrtok(NULL,Separators))!=NULL)
{
if (Groupkey_num==MEMBERSOF(Groupkey))
die("グループキーの数が多すぎます\n");
if (find_groupkey(p)>=0)
die("グループキー%sが二重に定義されています\n",p);
Groupkey[Groupkey_num].name = xstrdup(p);
Groupkey[Groupkey_num].keywordid = id;
Groupkey_num++;
}
return 0;
}
/*****************************************************************************/
/* メインプログラム */
/*****************************************************************************/
#define KEYWORD_DEF 0
#define KEYWORD_REF 1
#define GROUP 2
#define THROUGH 3
#define CUT 4
static int (*Command[3])(char *dst,char *src) =
{cmd_keyword_def,cmd_keyword_ref,cmd_group};
/*-----------------------------コマンド名の解析------------------------------*/
static int getcommandid(char *s)
{
static int isafterprogram = 0;
static int cutnum = 0; /* 削除するキーワードの数 */
static int throughnum = 6; /* 素通しするキーワードの数 */
static char *cuttable[256]; /* 削除するキーワード */
static char *throughtable[256] = /* 素通しするキーワード */
{"DRIVE","MAKE","DIR","README","MANUAL","COPY"};
int i;
strupr(s);
if (stricmp(s,"KEYWORD")==0)
{
if (isafterprogram)
return KEYWORD_REF;
else
return KEYWORD_DEF;
}
else if (stricmp(s,"GROUP")==0)
return GROUP;
else if (stricmp(s,"PROGRAM")==0)
{
isafterprogram = 1;
return THROUGH;
}
for (i=0 ; i<cutnum ; i++)
{
if (stricmp(s,cuttable[i])==0)
return CUT;
}
for (i=0 ; i<throughnum ; i++)
{
if (stricmp(s,throughtable[i])==0)
return THROUGH;
}
rep:
fprintf(stderr, "未定義のコマンドです %s\n"
"中止<A>,素通し<T>,削除<C>?",s);
i = getche();
putc('\n',stderr);
switch (i)
{
case 'A':
case 'a':
exit(1);
case 'T':
case 't':
if (throughnum == MEMBERSOF(throughtable))
die("THROUGHキーワードの数が多すぎます\n");
throughtable[throughnum++] = xstrdup(s);
return THROUGH;
case 'C':
case 'c':
if (cutnum==MEMBERSOF(cuttable))
die("CUTキーワードの数が多すぎます\n");
cuttable[cutnum++] = xstrdup(s);
return CUT;
default:
goto rep;
}
}
/*-----------------------------オプションの解析------------------------------*/
static void option(char *s)
{
switch (s[1])
{
case 'H':
case 'h': /* ヘルプは、明示的にオプションを指定して出力する */
case '?': /* ものだから、出力先はstdoutにする */
printf("MCFILTER ファイル名\n\n");
break;
default:
die("不正なオプションです %s\n",s);
}
}
/*------------------------------メインルーチン-------------------------------*/
extern int main(int argc,char **argv)
{
FILE *fpi;
char buf[2][512];
#define fpo stdout
while (++argv,--argc)
{
if (**argv=='-')
{
option(*argv);
continue;
}
if ((fpi=fopen(*argv,"r"))==NULL)
{
fprintf(stderr,"%sがオープンできません\n",*argv);
exit(1);
}
Linepos = 0;
while (fgets(buf[0],sizeof(buf[0]),fpi)!=NULL)
{
char *p,*q;
int id;
Linepos++;
p = chop(buf[0]);
if (*p=='\0' || *p=='#') /* 空行・コメント行の削除 */
continue;
q = strchr(p,':');
if (q==NULL)
die("不正な行です %s\n",p);
*q = '\0';
p = chop(p);
q = chop(q+1);
id = getcommandid(p);
if (id==CUT)
continue;
else if (id!=THROUGH)
{
if (!Command[id](buf[1],q))
continue;
q = buf[1];
}
fprintf(fpo,"%s:%s\n",p,q);
}
fclose(fpi);
}
return 0;
}
/*----------------------------End of MCFILTER.C------------------------------*/